local model_data = require"module/render/render_objects/voxel/model_data"
local model = require"module/render/render_objects/voxel/model"
local dkjson = require"library/dkjson"
local tileset = require"module/assets/tileset"

local assets = {
    _texture = {};
    _voxel = {};
    _font = {};
    _audio = {};
    _tileset = {};

    _tileset_i = 0;
    _tileset_index = {};
}

local audio_type = "_audio"
local voxel_type = "_voxel"
local font_type = "_font"
local texture_type = "_texture"

local match_table = {
    ["png"] = texture_type,
    ["jpg"] = texture_type,
    ["vox"] = voxel_type,
    ["ttf"] = font_type,
    ["otf"] = font_type,
    ["mp3"] = audio_type,
    ["ogg"] = audio_type,
    ["oga"] = audio_type,
    ["ogv"] = audio_type,
    ["wav"] = audio_type,
    ["abc"] = audio_type,
    ["mid"] = audio_type,
    ["pat"] = audio_type,
    ["amf"] = audio_type,
}

local load_func = {
    [texture_type] = function(path)
        return love.graphics.newImage(path)
    end;  
    [voxel_type] = function(path)
        return model_data(path)
    end;
    [audio_type] = function(path)
        local config_path = path .. "/.json"
        local config_file = love.filesystem.getInfo(config_path)
        local load_type = "stream"
        if config_file then
            load_type = dkjson.decode(config_file:read(),1,nil).type
        end
        return love.audio.newSource(path,load_type)
    end,
    [font_type] = function(path)
        local config_path = path .. "/.json"
        local config_file = love.filesystem.getInfo(config_path)
        local size = 12
        if config_file then
            size = dkjson.decode(config_file:read(),1,nil).size
        end
        return love.graphics.newFont(path,size)
    end
}

local function get_type(name)
    if not name then return nil end
    return match_table[name]
end

local function get_all_file_item(dir,tb)
    tb = tb or {}
    local fitem = love.filesystem.getDirectoryItems(dir)
    for k,name in ipairs(fitem) do
        local p = dir.."/"..name
        if dir == "" then
            p = name
        end
        local type =  love.filesystem.getInfo(p).type

        local file_type = get_type(name:match(".+%.(.+)"))
        if file_type then
            local item = {
                type = file_type;
                path = p;
            }
            table.insert(tb,item)
        end

        if type == "directory" then
            get_all_file_item(p,tb)
        end
    end
    return tb
end

function assets.load_all()
    local items = get_all_file_item("",{})
    for i,item in pairs(items) do
        assets[item.type][item.path] = load_func[item.type](item.path)
    end

    local tileset_items = love.filesystem.getDirectoryItems("assets/tileset")
    for _,name in ipairs(tileset_items) do
        local path = "assets/tileset".."/"..name
        local type =  love.filesystem.getInfo(path).type
        if type == "directory" then
            local t = tileset(path)
            assets._tileset[t.name] = t
            assets._tileset_index[assets._tileset_i] = t.name
            assets._tileset_i = assets._tileset_i + 1
        end
    end
end

function assets.texture(path)
    return assets._texture[path]
end

function assets.voxel(path)
    return assets._voxel[path]
end

function assets.create_model(model_data)
    if type(model_data) == "string" then
        model_data = assets._voxel[model_data]
        if model_data then
            return model(model_data)
        end
    end

    return model(model_data)
end

function assets.font(path)
    return assets._font[path]
end

function assets.audio(path)
    return assets._audio[path]
end

function assets.tileset(tileset_name)
    if type(tileset_name) == "string" then
        return assets._tileset[tileset_name]
    end
    return assets._tileset[assets._tileset_index[tileset_name] or ""]
end

return assets